package com.apchernykh.types;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.apchernykh.ceskyrozhlas.basic.R;
import com.apchernykh.rozhlasapp.ui.IViewsExpirationListener;
import com.apchernykh.rozhlasapp.ui.NullViewsExpirationListener;
import com.apchernykh.rozhlasapp.ui.RozhlasAppBaseFragmentActivity;
import com.apchernykh.rozhlasapp.ui.stations.ScheduleDetailsFragment;
import com.apchernykh.rozhlasapp.ui.stations.StationDetailsActivity;
import com.apchernykh.rozhlasapp.ui.stations.StationListAdapter;
import com.apchernykh.rozhlasapp.utils.ConditionalLog;

import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.ListView;

public class StationListFragment extends android.support.v4.app.ListFragment implements
		IViewsExpirationListener {
	StationListAdapter mStationListAdapter;
	private boolean mDualPane;
	public StationInfo mShownStationInfo = null;
	public boolean mForceDbRefresh = false;

	@Override
	public void onPause() {
		super.onPause();
		RozhlasAppBaseFragmentActivity.mApplicationModel.mOnViewsExpiredListener = new NullViewsExpirationListener();
		;
	}

	@Override
	public void onActivityCreated(Bundle iSavedInstanceState) {
		super.onActivityCreated(iSavedInstanceState);

		// Give some text to display if there is no data. In a real
		// application this would come from a resource.
		setEmptyText(getText(R.string.stahovani_pockejte_prosim));

		if (RozhlasAppBaseFragmentActivity.mApplicationModel == null
				|| RozhlasAppBaseFragmentActivity.mApplicationModel.mStationsList == null) {
			return;// should never come to here
		}
		mStationListAdapter = new StationListAdapter(getActivity(),
				R.layout.station_item,
				RozhlasAppBaseFragmentActivity.mApplicationModel.mStationsList);
		setListAdapter(mStationListAdapter);

		// fragment directly in the containing UI.
		View aDetailsFrame = getActivity().findViewById(
				R.id.station_schedule_details);
		mDualPane = aDetailsFrame != null
				&& aDetailsFrame.getVisibility() == View.VISIBLE;

		if (mDualPane) {
			// In dual-pane mode, the list view highlights the selected item.
			getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
			// Make sure our UI is in the correct state.
			showDetails();
		}
	}

	private void refreshStationsList() {
		RozhlasAppBaseFragmentActivity.mApplicationModel.mStationsListLasUpdated = System.currentTimeMillis() ; 
		// TODO: ensure that refresh comes after stations list download
		AsyncTask<Integer, Integer, List<StationInfo>> aTask = new AsyncTask<Integer, Integer, List<StationInfo>>() {
			private List<StationInfo> reloadFromWeb() {
				List<StationInfo> aStationsWebList = new LinkedList<StationInfo>();
				if (!RozhlasAppBaseFragmentActivity.mApplicationModel.mInetInfo
						.isDownloadAllowed()) {
					RozhlasAppBaseFragmentActivity.mApplicationModel.mStationsListLasUpdated = 0;// refresh
																								// failed,
																								// expire
																								// immediately
					return aStationsWebList;
				}
				try {
					DocumentBuilderFactory aDbf = DocumentBuilderFactory
							.newInstance();
					DocumentBuilder aDb = aDbf.newDocumentBuilder();
					Document aDoc = aDb
							.parse(new InputSource(
									new URL(
											"http://www.rozhlas.cz/iradio/config/radioconfig.xml")
											.openStream()));
					aDoc.getDocumentElement().normalize();

					NodeList aNodeList = aDoc.getElementsByTagName("station");

					for (int aCurrentNode = 0; aCurrentNode < aNodeList.getLength(); aCurrentNode++) {
						StationInfo a = new StationInfo(aNodeList.item(aCurrentNode));
						if (a.mp3URL != null) {
							aStationsWebList.add(a);
						}
					}
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (Exception e) {
					ConditionalLog
							.d("loadInBackground Exception", e.toString());
				}
				return aStationsWebList;
			}

			@Override
			protected List<StationInfo> doInBackground(Integer... iParams) {
				try {
					StationListDBHelper aDB = new StationListDBHelper(
							getActivity().getApplicationContext());
					List<StationInfo> aStations = aDB.getStationsList();

					if (aStations.isEmpty() || mForceDbRefresh) {
						mForceDbRefresh = false;
						List<StationInfo> aStationsListWeb = reloadFromWeb();
						if (!aStationsListWeb.isEmpty()) {
							aDB.reset(aStationsListWeb);
							aStations = aStationsListWeb;
						}
					}
					return aStations;
				} catch (Exception e) {
					e.printStackTrace();
				}
				return null;
			}

			@Override
			protected void onPostExecute(List<StationInfo> iResult) {
				if (iResult != null && iResult.size() > 0) {
					RozhlasAppBaseFragmentActivity.mApplicationModel.mStationsList = mStationListAdapter
							.setData(iResult);
				}
			}
		};

		aTask.execute(0);
	}

	private void showDetails() {
		mShownStationInfo = RozhlasAppBaseFragmentActivity.mApplicationModel
				.getSelectedStationInfo();
		if (mShownStationInfo == null) {
			return;
		}
		// We can display everything in-place with fragments, so update
		// the list to highlight the selected item and show the data.
		getListView().setItemChecked(mShownStationInfo.mStationId, true);
		if (mDualPane) {
			// Check what fragment is currently shown, replace if needed.
			ScheduleDetailsFragment aDetails = (ScheduleDetailsFragment) getFragmentManager()
					.findFragmentById(R.id.station_schedule_details);
			if (aDetails == null
					|| aDetails.getShownIndex() != mShownStationInfo.mStationId) {
				// Make new fragment to show this selection.
				aDetails = ScheduleDetailsFragment
						.newInstance(mShownStationInfo.mStationId);

				// Execute a transaction, replacing any existing fragment
				// with this one inside the frame.
				FragmentTransaction aFragmentTransaction = getFragmentManager()
						.beginTransaction();
				aFragmentTransaction.replace(R.id.station_schedule_details, aDetails);
				aFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
						.commit();
			} else {
				// invalidate here?
			}
		} else {
			// Otherwise we need to launch a new activity to display
			// the dialog fragment with selected text.
			Intent aIntent = new Intent();
			aIntent.setClass(getActivity(), StationDetailsActivity.class);
			startActivity(aIntent);
		}
	}

	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		if (RozhlasAppBaseFragmentActivity.mApplicationModel.mStationSelected != -1) {
			getListView().setItemChecked(
					getListView().getCheckedItemPosition(), false);
			getListView()
					.setItemChecked(
							RozhlasAppBaseFragmentActivity.mApplicationModel.mStationSelected,
							true);
		}
		RozhlasAppBaseFragmentActivity.mApplicationModel.mOnViewsExpiredListener = this;
	}

	@Override
	public void onListItemClick(ListView iListView, View iView, int iPosition, long iId) {
		RozhlasAppBaseFragmentActivity.mApplicationModel.mStationSelected = iPosition;
		showDetails();
	}

	@Override
	public void onViewExpired() {
		getActivity().runOnUiThread(new Runnable() {
			@Override
			public void run() {
				try
				{
				if (RozhlasAppBaseFragmentActivity.mApplicationModel.getExpirationTime() < System
						.currentTimeMillis()) {
					refreshStationsList();
				}
				//
				getListView().invalidateViews();
				//Can throw "java.lang.IllegalStateException: Content view not yet created"
				if (mDualPane) {// details
					showDetails();
					ScheduleDetailsFragment.refresh(getFragmentManager()
							.findFragmentById(R.id.station_schedule_details));
				}
				}
				catch(IllegalStateException e)
				{
					ConditionalLog.e("As expected... Oups... Trying to refresh a view which either does not exist anymore or is not yest created ");
					e.printStackTrace();
				}
			}
		});
	}
}
